package com.atguigu.flink.chapter02;


import org.apache.flink.api.common.functions.FlatMapFunction;
import org.apache.flink.api.common.functions.MapFunction;
import org.apache.flink.api.common.typeinfo.Types;
import org.apache.flink.api.java.functions.KeySelector;
import org.apache.flink.api.java.tuple.Tuple2;
import org.apache.flink.streaming.api.datastream.DataStreamSource;
import org.apache.flink.streaming.api.datastream.KeyedStream;
import org.apache.flink.streaming.api.datastream.SingleOutputStreamOperator;
import org.apache.flink.streaming.api.environment.StreamExecutionEnvironment;
import org.apache.flink.util.Collector;

/*
flink词频统计的执行步骤：
    1、获取一个流的执行环境
    2、通过执行环境，从source读取数据，得到一个流
    3、对流做各种操作
    4、输出结果
    5、启动流的执行环境

什么时候可以使用拉姆达表达式：
    当接受的类型是一个接口，并且这个接口只有一个抽象方法

泛型：
    类型擦除
            源码 -> 编译成字节码  -> 加载虚拟机执行
                泛型只存在于源码中，编译成字节码之后，泛型会自动消失，泛型擦除
 */
public class WcUnBoundedLamda {
    public static void main(String[] args) throws Exception {
        //1、获取一个流的执行环境
        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
        env.setParallelism(1);

        //2、通过执行环境，从source读取数据，得到一个流
        DataStreamSource<String> fileStream = env.socketTextStream("hadoop102",8888);

        //3、对流做各种操作
        //3.1 对每行数据做切割
        SingleOutputStreamOperator<String> wordStream = fileStream.flatMap(new FlatMapFunction<String, String>() {
            @Override
            public void flatMap(String line, Collector<String> out) throws Exception {
                String[] words = line.split(" ");

                for (String word : words) {
                    out.collect(word);
                }
            }
        }).returns(Types.STRING);

        //3.2 给每个单词配置 1
        SingleOutputStreamOperator<Tuple2<String, Integer>> wordOneStream = wordStream
                .map( word -> Tuple2.of(word, 1))
                .returns(Types.TUPLE(Types.STRING,Types.INT)); //明确指定经过map之后流的类型

        //3.3 按照单词分组
        KeyedStream<Tuple2<String, Integer>, String> keyedStream = wordOneStream.keyBy(t -> t.f0);

        //3.4 按照分组聚合：前面是元组， 1 表示元组位置为1 的元素进行聚合
        SingleOutputStreamOperator<Tuple2<String, Integer>> result = keyedStream.sum(1);

        //4、输出结果
        result.print();

        //5、启动流的执行环境
        env.execute();
    }
}


//public class WcUnBoundedLamda {
//    public static void main(String[] args) throws Exception {
//        //1、获取一个流的执行环境
//        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        env.setParallelism(1);
//
//        //2、通过执行环境，从source读取数据，得到一个流
//        DataStreamSource<String> fileStream = env.socketTextStream("hadoop102",8888);
//
//        //3、对流做各种操作
//        //3.1 对每行数据做切割
//        SingleOutputStreamOperator<String> wordStream = fileStream.flatMap(new FlatMapFunction<String, String>() {
//            @Override
//            public void flatMap(String line, Collector<String> out) throws Exception {
//                String[] words = line.split(" ");
//
//                for (String word : words) {
//                    out.collect(word);
//                }
//            }
//        }).returns(Types.STRING);
//
//        //3.2 给每个单词配置 1
//        SingleOutputStreamOperator<Tuple2<String, Integer>> wordOneStream = wordStream
//                .map( word -> Tuple2.of(word, 1))
//                .returns(Types.TUPLE(Types.STRING,Types.INT)); //明确指定经过map之后流的类型
//
//        //3.3 按照单词分组
//        KeyedStream<Tuple2<String, Integer>, String> keyedStream = wordOneStream.keyBy(t -> t.f0);
//
//        //3.4 按照分组聚合：前面是元组， 1 表示元组位置为1 的元素进行聚合
//        SingleOutputStreamOperator<Tuple2<String, Integer>> result = keyedStream.sum(1);
//
//        //4、输出结果
//        result.print();
//
//        //5、启动流的执行环境
//        env.execute();
//    }
//}
//
//
//public class WcUnBoundedLamda {
//    public static void main(String[] args) throws Exception {
//        //1、获取一个流的执行环境
//        StreamExecutionEnvironment env = StreamExecutionEnvironment.getExecutionEnvironment();
//        env.setParallelism(1);
//
//        //2、通过执行环境，从source读取数据，得到一个流
//        DataStreamSource<String> fileStream = env.socketTextStream("hadoop102",8888);
//
//        //3、对流做各种操作
//        //3.1 对每行数据做切割
//        SingleOutputStreamOperator<String> wordStream = fileStream.flatMap(new FlatMapFunction<String, String>() {
//            @Override
//            public void flatMap(String line, Collector<String> out) throws Exception {
//                String[] words = line.split(" ");
//
//                for (String word : words) {
//                    out.collect(word);
//                }
//            }
//        }).returns(Types.STRING);
//
//        //3.2 给每个单词配置 1
//        SingleOutputStreamOperator<Tuple2<String, Integer>> wordOneStream = wordStream
//                .map( word -> Tuple2.of(word, 1))
//                .returns(Types.TUPLE(Types.STRING,Types.INT)); //明确指定经过map之后流的类型
//
//        //3.3 按照单词分组
//        KeyedStream<Tuple2<String, Integer>, String> keyedStream = wordOneStream.keyBy( t -> t.f0);
//
//        //3.4 按照分组聚合：前面是元组， 1 表示元组位置为1 的元素进行聚合
//        SingleOutputStreamOperator<Tuple2<String, Integer>> result = keyedStream.sum(1);
//
//        //4、输出结果
//        result.print();
//
//        //5、启动流的执行环境
//        env.execute();
//    }
//}